;; ================
;; DATA ABSTRACTION
;; ================

;; These procedures serve as an abstraction layer over the underlying data
;; structures used to represent data sets. Make sure to only ever use these
;; procedures, when dealing with data sets.

(define-module (dataset))

(use-modules
 ;; SRFI-1 for list procedures
 (srfi srfi-1)
 ;; SRFI-8 for `receive`
 (srfi srfi-8)
 (rnrs exceptions)
 (rnrs conditions)
 (utils)
 (utils list-utils)
 (data-point))

(define-public empty-dataset '())
(define-public dataset-empty? null?)
(define-public dataset-first car)
(define-public dataset-rest cdr)

(define-public dataset-range
  (lambda (data start end)
    "Get a range of values from the given data."
    (list-range data start end)))

(define-public dataset-length length)

(define-public dataset-filter
  (lambda (predicate data)
    (filter predicate data)))

(define-public dataset-partition
  (lambda (predicate data)
    (partition predicate data)
    #;(receive (part-pred-true part-pred-false)
        (partition predicate data)
      (values part-pred-true part-pred-false))))

(define-public dataset-map
  (lambda (procedure data)
    (map procedure data)))

(define-public dataset-take
  (lambda (data n)
    (take data n)))

(define-public dataset-drop
  (lambda (data n)
    (drop data n)))

(define-public dataset-reduce list-reduce)

(define-public dataset-get-col
  (lambda (data col-index)
    (dataset-map (lambda (data-point)
                   (data-point-get-col data-point col-index))
                 data)))

(define-public column-uniform?
  (lambda (column equal-test)
    "Check, whether all elements in the column are equal."
    (apply equal-test column)))


(define-public shuffle-dataset fisher-yates-shuffle)


(define-public dataset-get-columns
  (lambda (dataset)
    (cond
     ;; if the dataset is empty, then there are no columns
     [(dataset-empty? dataset) '()]
     [else
      (let ([column-indices
             (range 0 (data-point-length (dataset-first dataset)))])
        (map (lambda (ind) (dataset-get-col dataset ind))
             column-indices))])))

;; ==================
;; COLUMN ABSTRACTION
;; ==================
(define-public dataset-column-first car)
(define-public dataset-column-rest cdr)
(define-public dataset-column-empty? null?)
